package com.xishu.client;

import com.xishu.config.Config;
import com.xishu.config.Constant;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.*;

public class HttpClientUtil {

    public static final String APPLICATION_JSON = "application/json";
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    public static String get(String url, Map<String, String> paramMap) {
        HttpClient httpClient = null;

        try {
            httpClient = new DefaultHttpClient();

            HttpGet httpGet = new HttpGet(url);

            List<BasicNameValuePair> basicNameValuePairList = new ArrayList<>();

            URIBuilder uriBuilder = new URIBuilder(httpGet.getURI());

            Set<Map.Entry<String, String>> entries = paramMap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                uriBuilder.addParameter(key, value);
            }

            httpGet.setURI(uriBuilder.build());

            HttpResponse httpResponse = httpClient.execute(httpGet);
            HttpEntity entity = httpResponse.getEntity();
            if (entity != null) {
                String respData = EntityUtils.toString(entity, "UTF-8");
                logger.info("response data is {}", respData);
                return respData;
            }
        } catch (Exception e) {
            logger.error("e", e);
        } finally {
            if (httpClient != null) {
                httpClient.getConnectionManager().shutdown();
            }
        }

        return null;

    }

    /**
     * head
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static boolean head(String url, Map<String, String> paraMap) throws IOException {
        HttpClient httpClient = null;

        try {
            httpClient = new DefaultHttpClient();
            HttpHead httpHead = new HttpHead(url);

            Set<Map.Entry<String, String>> entries = paraMap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                httpHead.addHeader(entry.getKey(), entry.getValue());
            }

            HttpResponse httpResponse = httpClient.execute(httpHead);
            return httpResponse.getStatusLine().getStatusCode() == Constant.HTTP_STATUS_OK;
        } catch (Exception e) {
            logger.error("e", e);
            throw new IOException();
        } finally {
            if (httpClient != null) {
                httpClient.getConnectionManager().shutdown();
            }
        }
    }

    /**
     * PUT请求发送数据
     *
     * @param url
     * @param headers
     * @param map
     */
    public static String post(String url, Map<String, String> headers, Map<String, String> map) {
        try {
            HttpPost httpPost = new HttpPost(url);

            //设置HTTP头
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }

            //设置参数
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            Iterator iterator = map.entrySet().iterator();

            while (iterator.hasNext()) {
                Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
                list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
            }

            httpPost.setEntity(new UrlEncodedFormEntity(list, Charset.forName("utf-8")));

            HttpResponse httpResponse = execute(httpPost);

            HttpEntity entity = httpResponse.getEntity();
            if (entity != null) {
                //状态，该状态可用于判断，此处略
                logger.info("resp_status:" + httpResponse.getStatusLine().getStatusCode());
                Charset respCharset = ContentType.getOrDefault(entity).getCharset();
                String respData = EntityUtils.toString(entity, respCharset);
                logger.info("respData is {}", respData);

                return respData;
            }


        } catch (IOException e) {
            logger.error("e", e);
        }

        logger.info("maybe some error");
        return null;
    }


    /**
     * 以json方式请求数据
     *
     * @param url
     * @param headers
     * @param data
     */
    public static String jsonPut(String url, Map<String, String> headers, String data) {
        try {
            logger.info("url is {}", url);
            HttpPut httpPut = new HttpPut(url);

            //设置HTTP头
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpPut.setHeader(entry.getKey(), entry.getValue());
                }
            }

            httpPut.setHeader("Content-Type", APPLICATION_JSON);

            logger.info("data is " + data);
            StringEntity se = new StringEntity(data, Charset.forName("UTF-8"));
            se.setContentType(APPLICATION_JSON);
            httpPut.setEntity(se);

            //执行
            HttpResponse httpResponse = execute(httpPut);
            HttpEntity entity = httpResponse.getEntity();

            //状态，该状态可用于判断，此处略
            logger.info("resp_status:" + httpResponse.getStatusLine().getStatusCode());
            if (entity != null) {
                Charset respCharset = ContentType.getOrDefault(entity).getCharset();
                String respData = EntityUtils.toString(entity, respCharset);
                logger.info("respData is {}", respData);
                return respData;
            }
        } catch (IOException e) {
            logger.error("e", e);
        }

        logger.info("maybe some error");
        return null;
    }

    /**
     * 通过JSON格式获取
     *
     * @param url
     * @param headers
     * @param data
     * @return
     */
    public static String jsonGet(String url, Map<String, String> headers, Map<String, String> data) throws URISyntaxException {
        try {
            HttpGet httpGet = new HttpGet(url);

            //设置HTTP头
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpGet.setHeader(entry.getKey(), entry.getValue());
                }
            }

            httpGet.setHeader("Content-Type", APPLICATION_JSON);

            URIBuilder uriBuilder = new URIBuilder(httpGet.getURI());

            Set<Map.Entry<String, String>> entries = data.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                uriBuilder.addParameter(key, value);
            }

            httpGet.setURI(uriBuilder.build());
            logger.info("data is " + data);

            //执行
            HttpResponse httpResponse = execute(httpGet);

            HttpEntity entity = httpResponse.getEntity();
            if (entity != null) {
                //状态，该状态可用于判断，此处略
                logger.info("resp_status:" + httpResponse.getStatusLine().getStatusCode());
                Charset respCharset = ContentType.getOrDefault(entity).getCharset();
                String respData = EntityUtils.toString(entity, respCharset);
                logger.info("respData is {}", respData);

                return respData;
            }


        } catch (IOException e) {
            logger.error("e", e);
        }

        logger.info("maybe some error");
        return null;
    }

    public static HttpResponse execute(HttpRequestBase requestBase) throws IOException {
        HttpClient httpClient = null;
        HttpClientContext context = null;
        Config config = Config.getInstance();

        if (config.httpProxy() && config.isAliyun()) {
            Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", new MyConnectionSocketFactory())
                    .register("https", new MySSLConnectionSocketFactory(SSLContexts.createSystemDefault())).build();
            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg, new FakeDnsResolver());
            httpClient = HttpClients.custom().setConnectionManager(cm).build();

            InetSocketAddress socksaddr = new InetSocketAddress("127.0.0.1", 1080);
            context = HttpClientContext.create();
            context.setAttribute("socks.address", socksaddr);

            logger.info("add the proxy");
        } else {
            httpClient = new DefaultHttpClient();
        }

        HttpResponse httpResponse = null;
        //执行
        if (context != null) {
            httpResponse = httpClient.execute(requestBase, context);
        } else {
            httpResponse = httpClient.execute(requestBase);
        }

        return httpResponse;

    }

}
